// const getArr = <T>(value: T, times: number = 5): T[] => {
//   return new Array(times).fill(value)
// }

// function getArr<T>(value: T, times: number = 5): T[] {
//   return new Array(times).fill(value)
// }
// console.log(getArr<number>(2, 3).map(item => item))

// const getArray = <T, U>(param1: T, params2: U, times: number): [T, U][] => {
//   return new Array(times).fill([param1, params2])
// }

// getArray<number, string>(1, '2', 4).forEach(item => {
//   console.log(item[0])
//   console.log(item[1].length)
// })

// let add = function <T>(arg: T, times: number) {
//   return arg
// }
// ;(() => {
//   let add: <T>(x: T, y: number) => T[] = (x: any, y: number) => {
//     return [x, y]
//   }
//   add(1, 2)

//   const abc: (x: number, y: number) => number = (x: number, y: number) => x + y
//   abc(1, 2)
// })()

function aaa(x: string, y: string): void
function aaa(x: number, y: number): void
function aaa(x: any, y: any): void {
  console.log(x, y)
}

const bbb = function <T>(x: T, y?: number): T[] {
  return [x]
}

bbb<string>('2')

const ccc = <T>(x: T, y?: number): T[] => {
  return [x]
}
ccc(3)

function ddd<T>(x: number, y: T): T[] {
  return [y]
}

let eee: <T>(x: T, y: number) => T[]

eee = <T>(x: T, y: number): T[] => {
  return [x]
}

eee(1, 2)

type fff = <T>(x: T) => T

let lll: fff = (x: any) => {
  return x
}

lll(3)

interface jjj<T> {
  (x: T): T
}

const qqq: jjj<string> = (x: string) => {
  return x
}

interface ggg<T> {
  a: T
  b: T
}

const hhh: ggg<string> = {
  a: '3',
  b: '2',
}

// 泛型约束

interface Ilength {
  length: number
}

const constraint = <T extends Ilength>(x: T, y: number) => {
  console.log('11111')
}
constraint([1, 2], 22)

function getPropName<T, K extends keyof T>(object: T, propName: K) {
  console.log(object[propName])
}

let obj = {
  a: 1,
  b: 2,
}

getPropName(obj, 'a')
// getPropName(obj, 'c')
